package com.example.demo.config.datasource;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import com.example.demo.config.annotation.SwitchSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager;

import javax.sql.DataSource;
import javax.transaction.UserTransaction;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: njz
 * @Description:
 * @Date: create in 2022/6/6 14:48
 */

@Configuration
public class MybatisConfig {

    /**
     * @Bean：向IOC容器中注入一个Bean
     * @ConfigurationProperties：使得配置文件中以spring.datasource为前缀的属性映射到Bean的属性中
     */
    @ConfigurationProperties(prefix = "spring.datasource.master")
    @Bean("master")
    @Primary
    public DataSource dataSource(Environment env){
        DriverManagerDataSource dataSource =new DriverManagerDataSource();

        dataSource.setDriverClassName(env.getProperty("spring.datasource.master.driver-class-name"));

        dataSource.setUrl(env.getProperty("spring.datasource.master.url"));

        dataSource.setUsername(env.getProperty("spring.datasource.master.username"));

        dataSource.setPassword(env.getProperty("spring.datasource.master.password"));

        return dataSource;
    }

    /**
     * 向IOC容器中注入另外一个数据源
     * 全局配置文件中前缀是spring.datasource.his
     */
    @Bean("slave")
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource hisDataSource(Environment env) {
        DriverManagerDataSource dataSource =new DriverManagerDataSource();

        dataSource.setDriverClassName(env.getProperty("spring.datasource.slave.driver-class-name"));

        dataSource.setUrl(env.getProperty("spring.datasource.slave.url"));

        dataSource.setUsername(env.getProperty("spring.datasource.slave.username"));

        dataSource.setPassword(env.getProperty("spring.datasource.slave.password"));

        return dataSource;
    }

    /**
     * 构建一个动态数据源，用以数据源的切换
     * @param master
     * @param slave
     * @return
     */
    @Bean(name = "dynamicDataSource")
    public DynamicDataSource dynamicDataSource(@Qualifier("master") DataSource master, @Qualifier("slave") DataSource slave) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object,Object> mapDataSource = new HashMap<Object,Object>(2);
        mapDataSource.put("master",master);
        mapDataSource.put("slave",slave);
        //将master数据源作为指定的数据源
        dynamicDataSource.setDefaultDataSource(master);
        //将master和slave数据源作为指定的数据源
        dynamicDataSource.setDataSource(mapDataSource);
        return dynamicDataSource;
    }

    /**
     * 创建动态数据源的SqlSessionFactory，传入的是动态数据源
     * @Primary这个注解很重要，如果项目中存在多个SqlSessionFactory，这个注解一定要加上
     */
    @Primary
    @Bean("sqlSessionFactory2")
    public SqlSessionFactory sqlSessionFactoryBean(@Qualifier("dynamicDataSource") DynamicDataSource dynamicDataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource);
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setDefaultFetchSize(100);
        configuration.setDefaultStatementTimeout(30);
        sqlSessionFactoryBean.setConfiguration(configuration);
        return sqlSessionFactoryBean.getObject();
    }

    /**
     * 重写事务管理器，管理动态数据源
     */
//    @Primary
//    @Bean(value = "transactionManager2")
//    public PlatformTransactionManager annotationDrivenTransactionManager(DynamicDataSource dataSource) {
//        return new DataSourceTransactionManager(dataSource);
//    }

    @Bean//创建事务管理器
    public JtaTransactionManager regTransactionManager () {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        UserTransaction userTransaction = new UserTransactionImp();
        return new JtaTransactionManager(userTransaction, userTransactionManager);
    }

}
